package org.dftproject.genesis.ui.pages.pedigree.tree;

import org.dftproject.genesis.data.genealogy.GenealogyConstants;
import org.dftproject.genesis.data.genealogy.GenealogyUtils;
import org.dftproject.genesis.data.genealogy.IName;
import org.dftproject.genesis.data.genealogy.IPerson;
import org.dftproject.genesis.data.genealogy.Sex;
import org.dftproject.genesis.ui.SharedImages;
import org.dftproject.genesis.ui.figures.dualtree.ISelectableFigure;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;

public class CoupleFigure extends AlphaFigure implements ISelectableFigure {
	
	private final Font boldFont = JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);

	public static final Color backgroundColor = new Color(null, 0xDD, 0xDD, 0xFF);
	public static final Color backgroundSelectedColor = new Color(null, 0xBB, 0xBB, 0xFF);
	public static final Color borderColor = new Color(null, 0x88, 0x88, 0x88);
	public static final Color borderSelectedColor = new Color(null, 0x66, 0x66, 0x66);
	public static final Color textColor = ColorConstants.black;
	public static final Color textSelectedColor = ColorConstants.black;
	public static final Color endColor = new Color(null, 0xAA, 0xAA, 0xAA);
	public static final Color endSelectedColor = new Color(null, 0x88, 0x88, 0x88);
	public static final Color unsetColor = new Color(null, 0xCC, 0xCC, 0xCC);
	public static final Color unsetSelectedColor = new Color(null, 0xAA, 0xAA, 0xAA);

	private final Dimension corner = new Dimension(8, 8);
	private final int lineWidth = 2;
	private final int endWidth = 4;

	private boolean selected = false;

	private final Label label1;
	private final Label label2;

	private final IPerson person1;
	private final IPerson person2;
	
	private Boolean left;
	private Boolean right;

	public CoupleFigure(IPerson p1, IPerson p2) {
		person1 = p1;
		if (p1 == null)
			left = false;
		person2 = p2;
		if (p2 == null)
			right = false;
		
		setBorder(new MarginBorder(4, 4 + endWidth, 4, 6 + endWidth));
		setLayoutManager(new FixedWidthColumnLayout(200, 2));

		label1 = new Label();
		label1.setLabelAlignment(PositionConstants.LEFT);
		label1.setFont(boldFont);
		label1.setForegroundColor(textColor);
		add(label1);

		label2 = new Label();
		label2.setLabelAlignment(PositionConstants.LEFT);
		label2.setFont(boldFont);
		label2.setForegroundColor(textColor);
		add(label2);

		setRequestFocusEnabled(true);
		addMouseListener(new MouseListener.Stub() {

			@Override
			public void mousePressed(MouseEvent me) {
				requestFocus();
				me.consume();

				setSelected(true);
			}

		});

		updateLabel(label1, p1);
		updateLabel(label2, p2);
	}

	public IPerson getPerson1() {
		return person1;
	}

	public IPerson getPerson2() {
		return person2;
	}

	public void setSelected(boolean selected) {
		if (this.selected == selected)
			return;

		this.firePropertyChange(ISelectableFigure.SELECTION_PROPERTY, this.selected, selected);
		this.selected = selected;

		label1.setForegroundColor(selected ? textSelectedColor : textColor);
		label2.setForegroundColor(selected ? textSelectedColor : textColor);

		repaint();
	}

	public boolean isSelected() {
		return selected;
	}

	protected void updateLabel(Label label, IPerson person) {
		IName name = null;
		Sex sex = null;
		if (person != null) {
			name = (IName) GenealogyUtils.getValue(person, GenealogyConstants.name, IName.class);
			sex = (Sex) GenealogyUtils.getValue(person, GenealogyConstants.sex, Sex.class);
		}

		if (name == null)
			label.setText("");
		else
			label.setText(GenealogyUtils.stringFromName(name));

		if (sex == null)
			label.setIcon(SharedImages.getDefault().getImage(SharedImages.IMG_NULL));
		else if (sex == Sex.Male)
			label.setIcon(SharedImages.getDefault().getImage(SharedImages.IMG_MALE));
		else if (sex == Sex.Female)
			label.setIcon(SharedImages.getDefault().getImage(SharedImages.IMG_FEMALE));
	}

	@Override
	public void paintFigure(Graphics graphics) {
		super.paintFigure(graphics);
		
		Rectangle bounds = getBounds();

		graphics.setBackgroundColor(selected ? backgroundSelectedColor : backgroundColor);
		graphics.setAntialias(SWT.OFF);
		graphics.fillRoundRectangle(bounds.getCropped(new Insets(lineWidth / 2)), corner.width, corner.height);

		if (!Boolean.TRUE.equals(left) || !Boolean.TRUE.equals(right)) {
			graphics.pushState();
			
			if (!Boolean.TRUE.equals(left)) {
				Rectangle clipRect = bounds.getCropped(new Insets(0, bounds.width - endWidth - lineWidth, 0, 0)).crop(new Insets(0, 0, bounds.height / 2, 0));
				graphics.setClip(clipRect);
				graphics.setBackgroundColor(selected ? (left != null ? endSelectedColor : unsetSelectedColor) : (left != null ? endColor : unsetColor));
				graphics.fillRoundRectangle(bounds.getCropped(new Insets(lineWidth / 2)), corner.width, corner.height);
			}
			
			if (!Boolean.TRUE.equals(right)) {
				Rectangle clipRect = bounds.getCropped(new Insets(0, bounds.width - endWidth - lineWidth, 0, 0)).crop(new Insets(bounds.height / 2, 0, 0, 0));
				graphics.setClip(clipRect);
				graphics.setBackgroundColor(selected ? (right != null ? endSelectedColor : unsetSelectedColor) : (right != null ? endColor : unsetColor));
				graphics.fillRoundRectangle(bounds.getCropped(new Insets(lineWidth / 2)), corner.width, corner.height);
			}

			graphics.popState();
		}
	}
	
	@Override
	protected void paintBorder(Graphics graphics) {
		super.paintBorder(graphics);
		
		graphics.setForegroundColor(selected ? borderSelectedColor : borderColor);

		graphics.setLineWidth(lineWidth);
		graphics.setAntialias(SWT.ON);
		graphics.drawRoundRectangle(bounds.getCropped(new Insets(lineWidth / 2)), corner.width, corner.height);
	}

	public void setLeft(boolean exists) {
		left = exists;
	}
	
	public void setRight(boolean exists) {
		right = exists;
	}

}
